package com.tarena.lbs.basic.web.service;

import com.alibaba.nacos.common.utils.CollectionUtils;
import com.github.pagehelper.PageInfo;
import com.tarena.lbs.attach.api.AttachApi;
import com.tarena.lbs.base.common.utils.Asserts;
import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.base.protocol.pager.PageResult;
import com.tarena.lbs.basic.web.repository.AdminRepository;
import com.tarena.lbs.basic.web.repository.BusinessRepository;
import com.tarena.lbs.basic.web.repository.EventRepository;
import com.tarena.lbs.basic.web.repository.StoreRepository;
import com.tarena.lbs.common.passport.enums.Roles;
import com.tarena.lbs.common.passport.principle.UserPrinciple;
import com.tarena.lbs.common.security.utils.LbsSecurityContenxt;
import com.tarena.lbs.pojo.attach.param.PicUpdateParam;
import com.tarena.lbs.pojo.basic.entity.StoreSearchEntity;
import com.tarena.lbs.pojo.basic.event.LocationStoreEvent;
import com.tarena.lbs.pojo.basic.param.StoreParam;
import com.tarena.lbs.pojo.basic.param.UserLocationParam;
import com.tarena.lbs.pojo.basic.po.AdminPO;
import com.tarena.lbs.pojo.basic.po.BusinessPO;
import com.tarena.lbs.pojo.basic.po.StorePO;
import com.tarena.lbs.pojo.basic.query.AreaStoreQuery;
import com.tarena.lbs.pojo.basic.query.StoreQuery;
import com.tarena.lbs.pojo.basic.vo.StoreVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class StoreService {
    @Autowired
    private AdminRepository adminRepository;
    @Autowired
    private StoreRepository storeRepository;
    @Autowired
    private BusinessRepository businessRepository;
    @Autowired
    private EventRepository eventRepository;

    public PageResult<StoreVO> storePage(StoreQuery query) throws BusinessException {
        //1、那认证
        UserPrinciple userPrinciple = LbsSecurityContenxt.getLoginToken();
        // 2、断言 不存在认证对象 抛异常
        Asserts.isTrue(userPrinciple==null,new BusinessException("-2","用户解析认证失败"));
        // 3、取角色
        Integer adminId = userPrinciple.getId();
        Roles role = userPrinciple.getRole();
        // 4、如果角色是SHOP 查询businessId 固定商家id lbs_admin
        if (role == Roles.SHOP){
            AdminPO adminPO = adminRepository.getAdminById(adminId);
            Asserts.isTrue(adminPO==null,new BusinessException("-2","商家信息不存在"));
            query.setBusinessId(adminPO.getBusinessId());
        }
        // 根据上述分支结果 封装完整的查询条件 有businessID和没有businessID
        //6、调用分页查询
        PageInfo<StorePO> pageInfo = storeRepository.getStores(query);
        //7、封装pageResul返回
        PageResult<StoreVO> voPages = new PageResult<>();
        voPages.setPageNo(pageInfo.getPageNum());
        voPages.setPageSize(pageInfo.getPageSize());
        voPages.setTotal(pageInfo.getTotal());
        List<StoreVO> vos = null;
        if (CollectionUtils.isNotEmpty(pageInfo.getList())){
            vos = pageInfo.getList().stream().map(po->{
                StoreVO vo = new StoreVO();
                BeanUtils.copyProperties(po,vo);
                return vo;
            }).collect(Collectors.toList());
        }
        voPages.setObjects(vos);
        return voPages;
    }

    //商家店铺的增加：
    public void storeSave(StoreParam storeParam) throws BusinessException {
        //1.检查角色是否是SHOP 读取认证对象 判断认证是否成功 判断角色是否相等
        checkRole(Roles.SHOP);
        //2.从入参中拿到店铺绑定的商家id 验证是否合法存在
        Integer businessId = storeParam.getBusinessId();
        BusinessPO bizPo = businessRepository.getBusiness(businessId);
        Asserts.isTrue(bizPo==null,new BusinessException("-2","商家信息不存在"));
        //3.封装 数据 补充属性 status状态 0正常 1禁用 createTime updateTime List-->String(url,url)
        StorePO poParam=storeParam2po(storeParam);
        //4.写入到数据层 写到mysql和es
        storeRepository.save(poParam);
        //5.po补充自动生成id 结合业务定义的图片类型 店铺门店图片List 店铺logo url TODO
        //店铺logo 300 店铺图片 400
        bindPictures(storeParam,poParam.getId());
    }
    //图片绑定商家
    @DubboReference
    private AttachApi attachApi;
    //将店铺入参 相关图片 分析成url 实际上传的是logoId imageIds
    private void bindPictures(StoreParam param,Integer bizId) {
        List<PicUpdateParam> pictures = new ArrayList<>();
        //封装一个店铺logo
        PicUpdateParam logoParam=new PicUpdateParam();
        logoParam.setBusinessId(bizId);
        logoParam.setBusinessType(300);
        //String logUuid = getFileUuidFromUrl(param.getStoreLogo());
        logoParam.setId(Integer.valueOf(param.getStoreLogo()));
        pictures.add(logoParam);
        //封装一个店铺门店的list
        List<PicUpdateParam> storeImages=null;
        storeImages=param.getStoreImagesIds().stream().map(strId->{
            PicUpdateParam storeImgParam=new PicUpdateParam();
                    storeImgParam.setBusinessId(bizId);
                    storeImgParam.setBusinessType(400);
                    storeImgParam.setId(Integer.valueOf(strId));
                    return storeImgParam;
                }
        ).collect(Collectors.toList());
        pictures.addAll(storeImages);
        attachApi.batchUpdateBusiness(pictures);

    }
    private String getFileUuidFromUrl(String url) {
        //拿到图片id或者fileUuid 这里需要再数据库中找到url 截取fileUuid作为绑定入参
        //http://localhost:9081/static/liencesFileUuid
        String[] splists = url.split("/");
        return splists[splists.length-1];
    }
    private StorePO storeParam2po(StoreParam storeParam) {
        StorePO poParam=new StorePO();
        //能拷贝的 大量表单属性 先拷贝
        BeanUtils.copyProperties(storeParam,poParam);
        //状态 0正常 1禁用
        poParam.setStoreStatus(0);
        Date now=new Date();
        poParam.setCreateTime(now);
        poParam.setUpdateTime(now);
        //入参地理位置,纬度和精度 latitude longitude但是po storeLatitude storeLongitude
        poParam.setStoreLatitude(storeParam.getLatitude());
        poParam.setStoreLongitude(storeParam.getLongitude());

        //显示图片的url
        String images="";//http://image1,http://image2,http//:image3
        List<String> storeImagesIds = storeParam.getStoreImagesIds();
        if (CollectionUtils.isNotEmpty(storeImagesIds)){
            for (int i=0;i<storeImagesIds.size();i++) {
                if (i==storeImagesIds.size()-1){
                    //数组url是最后一个元素 不在拼接,
                    images=images+storeImagesIds.get(i);
                }else{
                    //不是最后一个元素 需要最后拼接,
                    images=images+storeImagesIds.get(i)+",";
                }

            }
        }
        log.info("images:{}",images);
        poParam.setStoreImagesId(images);
        return poParam;
    }

    //新增商家店铺要进行判断用户权限
    private void checkRole(Roles roles) throws BusinessException {
        //直接使用断言,当前登录的用户角色 和业务需要得用户角色不相等 断言命中 抛异常
        UserPrinciple userPrinciple = LbsSecurityContenxt.getLoginToken();
        Asserts.isTrue(userPrinciple==null,new BusinessException("-2","用户解析认证失败"));
        //获取登录用户的角色
        Roles loginRole=userPrinciple.getRole();
        Asserts.isTrue(loginRole!=roles,new BusinessException("-2","角色不符合权限要求"));
    }

    public PageResult<StoreVO> getAreaStores(AreaStoreQuery query) throws BusinessException {
        //1.获取认证对象
        UserPrinciple userPrinciple = LbsSecurityContenxt.getLoginToken();
        Asserts.isTrue(userPrinciple==null,new BusinessException("-2","用户认证解析失败"));
        Integer adminId=userPrinciple.getId();
        AdminPO adminPo = adminRepository.getAdminById(adminId);
        Asserts.isTrue(adminPo==null,new BusinessException("-2","商家信息不存在"));
        //2.参数传递给仓储层
        List<StorePO> pos=storeRepository.getAreaStores(query,adminPo.getBusinessId());
        //3.封装假的pageResult给前端
        PageResult pageResult=new PageResult();
        pageResult.setTotal(10l);
        pageResult.setPageNo(1);
        pageResult.setPageSize(10);
        List<StoreVO> vos=pos.stream().map(po->{
            StoreVO vo=new StoreVO();
            BeanUtils.copyProperties(po,vo);
            return vo;
        }).collect(Collectors.toList());
        pageResult.setObjects(vos);
        return pageResult;
    }

    public void locationReport(UserLocationParam param) throws BusinessException {
        //1.获取认证对象
        UserPrinciple userPrinciple = LbsSecurityContenxt.getLoginToken();
        Asserts.isTrue(userPrinciple==null,new BusinessException("-2","用户认证解析失败"));
        Integer userId=userPrinciple.getId();
        //2.查询范围10公里 最近的5个店铺 使用ES
        List<StoreSearchEntity> stores=storeRepository.getNearestStores(param);
        //定位店铺如果是空的方法就结束了 本次定位上报没有业务执行
        if(CollectionUtils.isNotEmpty(stores)) {
            log.info("本次定位用户:{},定位到的店铺有:{}",userPrinciple.getNickname(),stores);
            // 3.将用户和店铺数据封装到消息数据 发送消息
            LocationStoreEvent event=new LocationStoreEvent();
            //当前接口认证解析的userId
            event.setUserId(userId);
            event.setStoreIds(stores.stream().map(entity->{return entity.getId();}).collect(Collectors.toList()));
            eventRepository.sendLocationStoreEvent(event);
        }else{
            log.info("本次定位用户:{},定位到的店铺是空的",userPrinciple.getNickname());
        }
    }
}
